package ui;
/**
 * NOLFrame is the JFrame for the GUI. 
 * Presents the library kiosk interface. 
 *  
 * @author Craig Markham
 * @date 12-01-12
 * @version 0.1
 */

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Types;
import java.util.ArrayList;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

@SuppressWarnings("serial")
public class NOLFrame extends JFrame {

	/**
	 * Default window size.
	 */
	private static final Dimension WINDOW_SIZE = new Dimension(800, 800);
	/**
	 * Default button size.
	 */
	private static final Dimension BUTTON_SIZE = new Dimension(350, 350);
	
	/**
	 * The text field that the user can scan their UserId in.
	 */
	private final JTextField my_user_field;

	/**
	 * The protected text field that user can fill out there password in.
	 */
	private final JPasswordField my_pw_field;

	/**
	 * The label to display any errors encountered in the program.
	 */
	private final JLabel my_error_label;
	
	/**
	 * The array list of text fields to accept user input.
	 */
	private final ArrayList<JTextField> my_fields;
	
	/**
	 * The table to show the results for searches.
	 */
	private JTable my_results;
	
	/**
	 * The panel to show the user what they request.
	 */
	private JPanel my_current_panel;

	/**
	 * The current user's login name.
	 */
	//private String my_username;

	/**
	 * The connection to the SQL database for the current user.
	 */
	private Connection my_connection;

	private JTextField my_book_field;
	
	/**
	 * Number of JTextFields to put in arraylist.
	 */
	private static final int FIELDS = 8;
	
	/**
	 * Constructs a welcome frame for the Nol Library program.
	 */
	public NOLFrame() {
		super("Library Kiosk");
		my_user_field = new JTextField();
		my_book_field = new JTextField();
		my_pw_field = new JPasswordField();
		my_error_label = new JLabel();
		my_error_label.setForeground(Color.RED);
		my_fields = new ArrayList<JTextField>();
		for (int i = 0; i < FIELDS; i++) {
			my_fields.add(new JTextField());
		}
		my_results = createSpringTable();
	}

	/**
	 * Sets up all panels, preferences, and shows the frame on screen.
	 */
	public void start() {
		setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		UIManager.put("Panel.background", Color.WHITE);

		my_current_panel = loginPanel();
		add(my_current_panel);
		setPreferredSize(WINDOW_SIZE);
		pack();
		setLocationRelativeTo(getRootPane());
		setVisible(true);
	}
	
	/**
	 * Creates a table that will automatically resize based on the content.
	 * 
	 * @return JTable with special resizing capabilities.
	 */
	private JTable createSpringTable () {
		JTable table = new JTable() {
			 
	         @Override
	         public Component prepareRenderer(TableCellRenderer renderer, int row,
	                 int column) {
	            Component component = super.prepareRenderer(renderer, row, column);
	            int rendererWidth = component.getPreferredSize().width;
	            TableColumn tableColumn = getColumnModel().getColumn(column);
	            tableColumn.setPreferredWidth(Math.max(rendererWidth +
	                    getIntercellSpacing().width,
	                    tableColumn.getPreferredWidth()));
	            return component;
	         }
	      };
	      table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
	      table.setEnabled(false);
	      return table;
	}
	
	/**
	 * Method to change the main panel to display the 
	 * requested panel.
	 * 
	 * @param the_panel - The new panel to display.
	 */
	public void switchContext(final JPanel the_panel) {
		remove(my_current_panel);
		my_current_panel = the_panel;
		add(my_current_panel);
		my_book_field.requestFocusInWindow();
		pack();
		repaint();

	}

	/**
	 * Returns a JPanel containing the text fields and button for logging in.
	 * 
	 * @return JPanel the panel with email text fields and submit button.
	 */
	private JPanel loginPanel() {
		final JPanel main_layout = new JPanel(new BorderLayout());
		
		final JPanel submit_panel = new JPanel(new BorderLayout());
		submit_panel.setBorder(BorderFactory
				.createTitledBorder("Enter your username and password:"));

		// Create ActionListener
		final ActionListener listener = new LoginButtonListener();

		final JPanel button_panel = buttonPanel("Login", "Login", listener);

		// Setup Username Field
		final JPanel un_pnl = new JPanel(new BorderLayout());
		my_user_field.addActionListener(listener);
		final JLabel user_label = new JLabel("Username:");
		un_pnl.add(user_label, BorderLayout.WEST);
		un_pnl.add(my_user_field, BorderLayout.CENTER);

		// Setup Password Field
		final JPanel pw_pnl = new JPanel(new BorderLayout());
		my_pw_field.addActionListener(listener);
		final JLabel pw_label = new JLabel("Password:");
		pw_pnl.add(pw_label, BorderLayout.WEST);
		pw_pnl.add(my_pw_field, BorderLayout.CENTER);

		// Add all to panel and return
		submit_panel.add(un_pnl, BorderLayout.NORTH);
		submit_panel.add(pw_pnl, BorderLayout.CENTER);
		submit_panel.add(button_panel, BorderLayout.SOUTH);

		main_layout.add(submit_panel, BorderLayout.NORTH);
		return main_layout;
	}
	
	
	/**
	 * Panel to show the initial panel after login.
	 * 
	 * @return Initial panel after login.
	 */
	private JPanel welcomePanel() {
		final JPanel main_layout = new JPanel(new BorderLayout());
		main_layout.add(topPanel(),  BorderLayout.CENTER);
		return main_layout;
	}
	
	
	/**
	 * Panel to show the initial panel after login.
	 * 
	 * @return Initial panel after login.
	 */
	private JPanel bookInfoPanel(final String theSource) {
		final JPanel main_layout = new JPanel(new BorderLayout());
		
		final JPanel submit_panel = new JPanel(new BorderLayout());
		my_book_field.setText(null);
		my_user_field.setText(null);
		submit_panel.setBorder(BorderFactory
				.createTitledBorder(theSource));

		// Create ActionListener
		final ActionListener listener = new BookButtonListener();

		final JPanel button_panel = buttonPanel(theSource, theSource, listener);

		// Setup Book ID Field
		final JPanel book_pnl = new JPanel(new BorderLayout());
		my_book_field.addActionListener(listener);
		
		final JLabel book_label = new JLabel("Book ID:");
		book_pnl.add(book_label, BorderLayout.WEST);
		book_pnl.add(my_book_field, BorderLayout.CENTER);

		// Setup User ID Field
		final JPanel user_pnl = new JPanel(new BorderLayout());
		my_user_field.addActionListener(listener);
		final JLabel user_label = new JLabel("User ID:");
		user_pnl.add(user_label, BorderLayout.WEST);
		user_pnl.add(my_user_field, BorderLayout.CENTER);

		// Add all to panel and return
		submit_panel.add(book_pnl, BorderLayout.NORTH);
		submit_panel.add(user_pnl, BorderLayout.CENTER);
		submit_panel.add(button_panel, BorderLayout.SOUTH);

		main_layout.add(submit_panel, BorderLayout.NORTH);
		main_layout.setName("book panel");
		my_book_field.getCursor();
		return main_layout;
	}
	
	/**
	 * Panel that contains the button and it's action for each of the 
	 * user choices.
	 * 
	 * @param the_text - The text to display on the button.
	 * @param the_name - The name of the button to create.
	 * @param the_al - The actionlistener for the button to use.
	 * @return JPanel holding the button and error label.
	 */
	private JPanel buttonPanel(final String the_text, final String the_name, 
			final ActionListener the_al) {
		// Create JButton Panel
		final JPanel submit_button_pnl = new JPanel(new FlowLayout(
				FlowLayout.RIGHT));
		final JButton submit_button = new JButton(the_text);
		submit_button.setSize(getMinimumSize());
		submit_button.addActionListener(the_al);
		submit_button.setName(the_name);
		submit_button.setPreferredSize(BUTTON_SIZE);
		submit_button_pnl.add(submit_button);
		
		//trigger the button so that the table is displayed on search
		if (the_name == "Patron Search" || the_name == "Book Search") {
			submit_button.doClick();
		}

		// Create Error Message Panel
		final JPanel message_panel = new JPanel(new FlowLayout(
				FlowLayout.CENTER));
		my_error_label.setText("");
		message_panel.add(my_error_label);

		//Setup Panel for Message/Button
		final JPanel bottom_panel = new JPanel(new BorderLayout());
		bottom_panel.add(message_panel, BorderLayout.WEST);
		bottom_panel.add(submit_button_pnl, BorderLayout.EAST);
		return bottom_panel;
	}
	
	/**
	 * Panel for the user to search for a patron.
	 * 
	 * @return The panel that holds components for 
	 * searching for patrons.
	 */
	private JPanel patronSearchPanel() {
		final String name = "Patron Search";
		final JPanel main_layout = new JPanel(new BorderLayout());
		main_layout.add(topPanel(), BorderLayout.NORTH);
		
		final JPanel content = new JPanel(new BorderLayout());
		final JLabel title = new JLabel(name);
		content.add(title, BorderLayout.NORTH);
		
		final JPanel input_panel = new JPanel(new BorderLayout());
		input_panel.setBorder(BorderFactory
				.createTitledBorder("Options"));
		
		input_panel.add(patronInput(), BorderLayout.CENTER);
		
		final ActionListener listener = new AddListener();
		final JPanel button_panel = buttonPanel("Search", name, listener);
		
		input_panel.add(button_panel, BorderLayout.SOUTH);
		
		content.add(input_panel, BorderLayout.CENTER);
		final JPanel squish = new JPanel(new BorderLayout());
		squish.add(content, BorderLayout.NORTH);
		
		final JScrollPane scroller = new JScrollPane(my_results);
		scroller.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
		scroller.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
		squish.add(scroller, BorderLayout.CENTER);
		
		main_layout.add(squish, BorderLayout.CENTER);
		return main_layout;
	}
	
	/**
	 * Panel that holds the textfields and labels for
	 * inputting patron data (for search and add).
	 * 
	 * @return panel containing textfields and labels.
	 */
	private JPanel patronInput() {
		final JPanel labels = new JPanel(new GridLayout(1, 1));
		final JPanel fields = new JPanel(new GridLayout(1, 1));
		labels.add(new JLabel("ID"));
		fields.add(my_fields.get(0));

		final JPanel labels_fields = new JPanel(new BorderLayout());
		labels_fields.add(fields, BorderLayout.CENTER);
		labels_fields.add(labels, BorderLayout.WEST);
		return labels_fields;
	}
	
	/**
	 * Panel that holds the welcome message and displays
	 * the links to each portion of the program.
	 * 
	 * @return navigation and welcome message panel.
	 */
	private JPanel topPanel() {
		final JPanel main_layout = new JPanel(new BorderLayout());
		
		final MouseListener link_listener = new ContextSwitchListener();
		
		final JLabel welcome = new JLabel();
		welcome.setText("Welcome to the Newport Oldtown Libary Self Checkout Kiosk");
		
		final JPanel welcome_center = new JPanel(new FlowLayout(FlowLayout.CENTER));
		welcome_center.add(welcome);
		
		final JButton book_checkout = new JButton();
		book_checkout.setText("<html><u>Book Checkout</u></html>");
		book_checkout.setForeground(Color.BLUE);
		book_checkout.setName("Book Checkout");
		book_checkout.setPreferredSize(BUTTON_SIZE);
		book_checkout.addMouseListener(link_listener);
		final JButton book_checkin = new JButton();
		book_checkin.setText("<html><u>Book Check In</u></html>");
		book_checkin.setForeground(Color.BLUE);
		book_checkin.setName("Book Check In");
		book_checkin.setPreferredSize(BUTTON_SIZE);
		book_checkin.addMouseListener(link_listener);
		final JButton patron_search = new JButton();
		patron_search.setText("<html><u>View Patron</u></html>");
		patron_search.setForeground(Color.BLUE);
		patron_search.setName("View Patron");
		patron_search.setPreferredSize(BUTTON_SIZE);
		patron_search.addMouseListener(link_listener);

		final JPanel links_center = new JPanel(new FlowLayout(FlowLayout.CENTER));
		links_center.add(book_checkout);
		links_center.add(book_checkin);
		links_center.add(patron_search);
		
		main_layout.add(welcome_center, BorderLayout.NORTH);
		main_layout.add(links_center, BorderLayout.CENTER);
		
		return main_layout;
	}

	/**
	 * Validates the user input for user and password against
	 * the SQL database user and password, and creates a connection
	 * to the database if the input is valid.
	 * 
	 * @param user - username
	 * @param pass - password
	 * @return boolean - whether or not the user is logged in.
	 */
	private boolean validate(final String user, final String pass) {
		boolean logged_in;
		String dbUrl = "jdbc:sqlserver://INSPIRON17:1433;" + "user=" + user
				+ ";password=" + pass;

		try {
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			my_connection = DriverManager.getConnection(dbUrl);

			//Script to automate login
				//my_connection =DriverManager.getConnection(
				//"jdbc:sqlserver://INSPIRON17:1433;user=nol_admin;password=sa");
			logged_in = true;
			
		} catch (final ClassNotFoundException e) {
			logged_in = false;
		} catch (final SQLException e) {
			logged_in = false;
		}
		return logged_in;
	}

	public void displayPatronResult(final ResultSet the_rs) {
		StringBuilder sb = new StringBuilder();

		try {
			if(the_rs.first()){
				sb.append("Patron Information: \nUserID:");
				sb.append(the_rs.getString(1));
				sb.append("\nName: ");
				sb.append(the_rs.getString(2));
				sb.append(" ");
				sb.append(the_rs.getString(3));
				sb.append("\nAddress: ");
				sb.append(the_rs.getString(4));
				sb.append("\nCity: ");
				sb.append(the_rs.getString(5));
				sb.append("\nState: ");
				sb.append(the_rs.getString(6));
				sb.append("\nZip: ");
				sb.append(the_rs.getString(7));
				sb.append("\nEmail: ");
				sb.append(the_rs.getString(8));
				sb.append("\nAccount Balance: ");
				sb.append(the_rs.getString(9));
			} else {
				sb.append("Operation did not complete. Please see ");
				sb.append("Librarian for assistance.");
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		JOptionPane.showMessageDialog(this, sb);		
	}
	
	public void displayResult(int the_result) {
		StringBuilder sb = new StringBuilder();
		if(the_result == 1){
		sb.append("Operation successfull");
		} else {
			sb.append("Operation did not complete. Please see ");
			sb.append("Librarian for assistance.");
		}
		JOptionPane.showMessageDialog(this, sb);		
	}

	/**
	 * ActionListener for the Login button. Logs in for the user if the
	 * name and password are valid. Otherwise displays an error.
	 */
	public class LoginButtonListener implements ActionListener {

		public void actionPerformed(final ActionEvent the_event) {
			
			if (my_user_field.getText().isEmpty()) {
				my_error_label.setText("Please enter your user name.");

			} else if (my_pw_field.getPassword().length == 0) {
				my_error_label.setText("Please enter your password.");
			} else {
				final String user = my_user_field.getText().trim();
				final String pass = new String(my_pw_field.getPassword());
				if (!validate(user, pass)) {
					my_error_label
							.setText("Incorrect login information. Please try again.");
				} else {
					my_error_label.setText("Login successful.");
					my_error_label.setForeground(Color.BLACK);
					switchContext(welcomePanel());
				}
				my_user_field.setText("");
				my_pw_field.setText("");
			}
			
			my_error_label.setText("Login successful.");
			my_error_label.setForeground(Color.BLACK);
			switchContext(welcomePanel());
		}
	}
	
	/**
	 * ActionListener for the Book Action button.
	 */
	public class BookButtonListener implements ActionListener {

		public void actionPerformed(final ActionEvent the_event) {
			if (my_book_field.getText().isEmpty()) {
				my_error_label.setText("Please scan the book.");

			} else if (my_user_field.getText().length() == 0) {
				my_error_label.setText("Please scan your library card.");
			} else {
				final String book = my_book_field.getText().trim();
				
				final String user = new String(my_user_field.getText().trim());
				try {
					final int bookID = Integer.parseInt(book);
					final int userID = Integer.parseInt(user);
	
					CallableStatement cstmt;
					if(the_event.getActionCommand().equals("Book Checkout")){
						try {
							cstmt = my_connection.prepareCall("{? = call CheckOutBook(?, ?)}");
							cstmt.setInt("BookID", bookID);
							cstmt.setInt("PatronID", userID);
							cstmt.registerOutParameter(1, Types.INTEGER);
							cstmt.execute();
							int returnValue = cstmt.getInt(1);
							displayResult(returnValue);
							
						} catch (SQLException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					} else if(the_event.getActionCommand().equals("Book Check In")){
						try {
							cstmt = my_connection.prepareCall("{? = call CheckInBook(?, ?)}");
							cstmt.setInt("BookID", bookID);
							cstmt.setInt("PatronID", userID);
							cstmt.registerOutParameter(1, Types.INTEGER);
							cstmt.execute();
							int returnValue = cstmt.getInt(1);
							displayResult(returnValue);
							
						} catch (SQLException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
					}
				} catch (NumberFormatException e){
					e.printStackTrace();
				}
				my_book_field.setText(null);
				my_user_field.setText(null);
			}
			switchContext(welcomePanel());
		}
	}
	
	/**
	 * ActionListener for the Patron Search button
	 */
	public class AddListener implements ActionListener {

		public void actionPerformed(final ActionEvent the_event) {
			String source = ((JButton)the_event.getSource()).getName();
			if (source == "Patron Search") {
				try {
					if (!my_fields.get(0).getText().trim().isEmpty()) {
						StringBuilder sb = new StringBuilder();
						sb.append("SELECT * FROM PATRON WHERE PatronID = ");
						sb.append(my_fields.get(0).getText().trim());
						sb.append(";");

						Statement st = my_connection.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE, 
							    ResultSet.CONCUR_READ_ONLY);

						ResultSet rs = st.executeQuery(sb.toString());
						displayPatronResult(rs);
					//clear text field
						my_fields.get(0).setText("");
					}
				} catch (final SQLException e) {
						my_error_label.setText(e.getMessage());
						my_error_label.setForeground(Color.RED);
				}
			}
		}
	}
		
	
	/**
	 * ActionListener for the Checkout button. 
	 */
	public class SearchListener implements ActionListener {

		public void actionPerformed(final ActionEvent the_event) {
			//Do Nothing
		}
	}
	
	/**
	 * MouseListener for determining which button the user has clicked on
	 * and switches the main panel determined by the button.
	 */
	public class ContextSwitchListener implements MouseListener {

		@Override
		public void mouseClicked(MouseEvent the_event) {
			String source = ((JButton)the_event.getSource()).getName();
			if(source == "Book Checkout") {
				switchContext(bookInfoPanel(source));
			} else if(source == "Book Check In") {
				switchContext(bookInfoPanel(source));
			} else if(source == "View Patron") {
				switchContext(patronSearchPanel());
			} else {
				//Do Nothing
			}
		}

		@Override
		public void mouseEntered(MouseEvent arg0) {
			//Do Nothing
		}

		@Override
		public void mouseExited(MouseEvent arg0) {
			//Do Nothing
		}

		@Override
		public void mousePressed(MouseEvent arg0) {
			//Do Nothing
		}

		@Override
		public void mouseReleased(MouseEvent arg0) {
			//Do Nothing
		}
	}
}
	
	